﻿Imports System
Imports System.CodeDom
Imports System.Diagnostics.CodeAnalysis
Imports System.Globalization
Imports System.Text
Imports System.Workflow.ComponentModel.Compiler

Namespace System.Workflow.Activities.Rules
    Friend Class ArrayCreateExpression
        Inherits RuleExpressionInternal
        ' Methods
        Friend Overrides Sub AnalyzeUsage(ByVal expression As CodeExpression, ByVal analysis As RuleAnalysis, ByVal isRead As Boolean, ByVal isWritten As Boolean, ByVal qualifier As RulePathQualifier)
            Dim expression2 As CodeArrayCreateExpression = DirectCast(expression, CodeArrayCreateExpression)
            If (Not expression2.SizeExpression Is Nothing) Then
                RuleExpressionWalker.AnalyzeUsage(analysis, expression2.SizeExpression, True, False, Nothing)
            End If
            Dim expression3 As CodeExpression
            For Each expression3 In expression2.Initializers
                RuleExpressionWalker.AnalyzeUsage(analysis, expression3, True, False, Nothing)
            Next
        End Sub

        Friend Overrides Function Clone(ByVal expression As CodeExpression) As CodeExpression
            Dim expression2 As CodeArrayCreateExpression = DirectCast(expression, CodeArrayCreateExpression)
            Dim expression3 As New CodeArrayCreateExpression { _
                .CreateType = TypeReferenceExpression.CloneType(expression2.CreateType), _
                .Size = expression2.Size _
            }
            If (Not expression2.SizeExpression Is Nothing) Then
                expression3.SizeExpression = RuleExpressionWalker.Clone(expression2.SizeExpression)
            End If
            Dim expression4 As CodeExpression
            For Each expression4 In expression2.Initializers
                expression3.Initializers.Add(RuleExpressionWalker.Clone(expression4))
            Next
            Return expression3
        End Function

        Friend Overrides Sub Decompile(ByVal expression As CodeExpression, ByVal stringBuilder As StringBuilder, ByVal parentExpression As CodeExpression)
            Dim childExpr As CodeArrayCreateExpression = DirectCast(expression, CodeArrayCreateExpression)
            Dim flag As Boolean = RuleDecompiler.MustParenthesize(childExpr, parentExpression)
            If flag Then
                stringBuilder.Append("(")
            End If
            stringBuilder.Append("new ")
            RuleDecompiler.DecompileType(stringBuilder, childExpr.CreateType)
            stringBuilder.Append("["c)
            If (Not childExpr.SizeExpression Is Nothing) Then
                RuleExpressionWalker.Decompile(stringBuilder, childExpr.SizeExpression, Nothing)
            ElseIf ((childExpr.Size <> 0) OrElse (childExpr.Initializers.Count = 0)) Then
                stringBuilder.Append(childExpr.Size)
            End If
            stringBuilder.Append("]"c)
            If (childExpr.Initializers.Count > 0) Then
                stringBuilder.Append(" { ")
                Dim i As Integer
                For i = 0 To childExpr.Initializers.Count - 1
                    Dim expression3 As CodeExpression = childExpr.Initializers.Item(i)
                    If (expression3 Is Nothing) Then
                        Dim exception As New RuleEvaluationException(String.Format(CultureInfo.CurrentCulture, Messages.NullConstructorTypeParameter, New Object() { i.ToString(CultureInfo.CurrentCulture), childExpr.CreateType }))
                        exception.Data.Item("ErrorObject") = childExpr
                        Throw exception
                    End If
                    If (i > 0) Then
                        stringBuilder.Append(", ")
                    End If
                    RuleExpressionWalker.Decompile(stringBuilder, expression3, Nothing)
                Next i
                stringBuilder.Append("}"c)
            End If
            If flag Then
                stringBuilder.Append(")")
            End If
        End Sub

        Friend Overrides Function Evaluate(ByVal expression As CodeExpression, ByVal execution As RuleExecution) As RuleExpressionResult
            Dim expression2 As CodeArrayCreateExpression = DirectCast(expression, CodeArrayCreateExpression)
            If (expression2.CreateType Is Nothing) Then
                Dim exception As New RuleEvaluationException(Messages.NullTypeType)
                exception.Data.Item("ErrorObject") = expression2
                Throw exception
            End If
            Dim info As RuleExpressionInfo = execution.Validation.ExpressionInfo(expression2)
            If (expression2 Is Nothing) Then
                Dim exception2 As New InvalidOperationException(Messages.ExpressionNotValidated)
                exception2.Data.Item("ErrorObject") = expression2
                Throw exception2
            End If
            Dim elementType As Type = info.ExpressionType.GetElementType
            Dim length As Integer = 0
            If (Not expression2.SizeExpression Is Nothing) Then
                Dim expressionType As Type = execution.Validation.ExpressionInfo(expression2.SizeExpression).ExpressionType
                Dim result As RuleExpressionResult = RuleExpressionWalker.Evaluate(execution, expression2.SizeExpression)
                If (expressionType Is GetType(Integer)) Then
                    length = CInt(result.Value)
                ElseIf (expressionType Is GetType(Long)) Then
                    length = CInt(CLng(result.Value))
                ElseIf (expressionType Is GetType(UInt32)) Then
                    length = CInt(DirectCast(result.Value, UInt32))
                ElseIf (expressionType Is GetType(UInt64)) Then
                    length = CInt([CULng](result.Value))
                End If
            ElseIf (expression2.Size <> 0) Then
                length = expression2.Size
            Else
                length = expression2.Initializers.Count
            End If
            Dim literal As Array = Array.CreateInstance(elementType, length)
            If (Not expression2.Initializers Is Nothing) Then
                Dim i As Integer
                For i = 0 To expression2.Initializers.Count - 1
                    Dim expression3 As CodeExpression = expression2.Initializers.Item(i)
                    Dim operandType As Type = execution.Validation.ExpressionInfo(expression3).ExpressionType
                    Dim result2 As RuleExpressionResult = RuleExpressionWalker.Evaluate(execution, expression3)
                    literal.SetValue(Executor.AdjustType(operandType, result2.Value, elementType), i)
                Next i
            End If
            Return New RuleLiteralResult(literal)
        End Function

        Friend Overrides Function Match(ByVal expression As CodeExpression, ByVal comperand As CodeExpression) As Boolean
            Dim expression2 As CodeArrayCreateExpression = DirectCast(expression, CodeArrayCreateExpression)
            Dim expression3 As CodeArrayCreateExpression = [TryCast](comperand,CodeArrayCreateExpression)
            If (((expression3 Is Nothing) OrElse (expression2.Size <> expression3.Size)) OrElse Not TypeReferenceExpression.MatchType(expression2.CreateType, expression3.CreateType)) Then
                Return False
            End If
            If (Not expression2.SizeExpression Is Nothing) Then
                If (expression3.SizeExpression Is Nothing) Then
                    Return False
                End If
                If Not RuleExpressionWalker.Match(expression2.SizeExpression, expression3.SizeExpression) Then
                    Return False
                End If
            ElseIf (Not expression3.SizeExpression Is Nothing) Then
                Return False
            End If
            If (expression2.Initializers.Count <> expression3.Initializers.Count) Then
                Return False
            End If
            Dim i As Integer
            For i = 0 To expression2.Initializers.Count - 1
                If Not RuleExpressionWalker.Match(expression2.Initializers.Item(i), expression3.Initializers.Item(i)) Then
                    Return False
                End If
            Next i
            Return True
        End Function

        <SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")> _
        Friend Overrides Function Validate(ByVal expression As CodeExpression, ByVal validation As RuleValidation, ByVal isWritten As Boolean) As RuleExpressionInfo
            Dim newParent As CodeArrayCreateExpression = DirectCast(expression, CodeArrayCreateExpression)
            If isWritten Then
                Dim item As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.CannotWriteToExpression, New Object() { GetType(CodeObjectCreateExpression).ToString }), &H17A)
                item.UserData.Item("ErrorObject") = newParent
                validation.Errors.Add(item)
                Return Nothing
            End If
            If (newParent.CreateType Is Nothing) Then
                Dim error2 As New ValidationError(Messages.NullTypeType, &H53D)
                error2.UserData.Item("ErrorObject") = newParent
                validation.Errors.Add(error2)
                Return Nothing
            End If
            Dim lhsType As Type = validation.ResolveType(newParent.CreateType)
            If (lhsType Is Nothing) Then
                Return Nothing
            End If
            If lhsType.IsArray Then
                Dim error3 As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.ArrayTypeInvalid, New Object() { lhsType.Name }), &H53D)
                error3.UserData.Item("ErrorObject") = newParent
                validation.Errors.Add(error3)
                Return Nothing
            End If
            Try 
                If Not validation.PushParentExpression(newParent) Then
                    Return Nothing
                End If
                If (newParent.Size < 0) Then
                    Dim error4 As New ValidationError(Messages.ArraySizeInvalid, &H53D)
                    error4.UserData.Item("ErrorObject") = newParent
                    validation.Errors.Add(error4)
                    Return Nothing
                End If
                If (Not newParent.SizeExpression Is Nothing) Then
                    Dim info As RuleExpressionInfo = RuleExpressionWalker.Validate(validation, newParent.SizeExpression, False)
                    If (info Is Nothing) Then
                        Return Nothing
                    End If
                    If (((Not info.ExpressionType Is GetType(Integer)) AndAlso (Not info.ExpressionType Is GetType(UInt32))) AndAlso ((Not info.ExpressionType Is GetType(Long)) AndAlso (Not info.ExpressionType Is GetType(UInt64)))) Then
                        Dim error5 As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.ArraySizeTypeInvalid, New Object() { info.ExpressionType.Name }), &H53D)
                        error5.UserData.Item("ErrorObject") = newParent
                        validation.Errors.Add(error5)
                        Return Nothing
                    End If
                End If
                Dim flag As Boolean = False
                Dim i As Integer
                For i = 0 To newParent.Initializers.Count - 1
                    Dim expression3 As CodeExpression = newParent.Initializers.Item(i)
                    If (expression3 Is Nothing) Then
                        Dim error6 As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.MissingInitializer, New Object() { lhsType.Name }), &H53D)
                        error6.UserData.Item("ErrorObject") = newParent
                        validation.Errors.Add(error6)
                        Return Nothing
                    End If
                    Dim info2 As RuleExpressionInfo = RuleExpressionWalker.Validate(validation, expression3, False)
                    If (info2 Is Nothing) Then
                        flag = True
                    Else
                        Dim error7 As ValidationError
                        If Not RuleValidation.StandardImplicitConversion(info2.ExpressionType, lhsType, expression3, error7) Then
                            If (Not error7 Is Nothing) Then
                                error7.UserData.Item("ErrorObject") = newParent
                                validation.Errors.Add(error7)
                            End If
                            error7 = New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.InitializerMismatch, New Object() { i, lhsType.Name }), &H545)
                            error7.UserData.Item("ErrorObject") = newParent
                            validation.Errors.Add(error7)
                            Return Nothing
                        End If
                    End If
                Next i
                If flag Then
                    Return Nothing
                End If
                Dim size As Double = -1
                If (Not newParent.SizeExpression Is Nothing) Then
                    Dim sizeExpression As CodePrimitiveExpression = [TryCast](newParent.SizeExpression,CodePrimitiveExpression)
                    If ((Not sizeExpression Is Nothing) AndAlso (Not sizeExpression.Value Is Nothing)) Then
                        size = CDbl(Executor.AdjustType(sizeExpression.Value.GetType, sizeExpression.Value, GetType(Double)))
                    End If
                    If (newParent.Size > 0) Then
                        Dim error8 As New ValidationError(Messages.ArraySizeBoth, &H53D)
                        error8.UserData.Item("ErrorObject") = newParent
                        validation.Errors.Add(error8)
                        Return Nothing
                    End If
                ElseIf (newParent.Size > 0) Then
                    size = newParent.Size
                End If
                If ((size >= 0) AndAlso (newParent.Initializers.Count > size)) Then
                    Dim error9 As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.InitializerCountMismatch, New Object() { newParent.Initializers.Count, size }), &H545)
                    error9.UserData.Item("ErrorObject") = newParent
                    validation.Errors.Add(error9)
                    Return Nothing
                End If
            Finally
                validation.PopParentExpression
            End Try
            Return New RuleExpressionInfo(lhsType.MakeArrayType)
        End Function

    End Class
End Namespace

